/*
 * SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD
 *
 * SPDX-License-Identifier: Unlicense OR CC0-1.0
 */
#include <esp_log.h>
#include <freertos/FreeRTOS.h>
#include <freertos/task.h>
#include <nvs_flash.h>
#include <esp_err.h>
#include <esp_rmaker_core.h>
#include <esp_rmaker_ota.h>
#include <esp_rmaker_schedule.h>
#include <esp_rmaker_common_events.h>
#include <esp_rmaker_standard_types.h>
#include <esp_rmaker_standard_devices.h>
#include <esp_rmaker_standard_params.h>
#include "esp_rmaker_utils.h"

#include "bsp/esp-box-3.h"
#include <app_network.h>
#include "app_sntp.h"
#include "app_aht30.h"
#include "app_sr_tts.h"
#include "app_driver.h"
#include "ui/ui.h"
#include "app_rmker.h"

static const char *TAG = "rmaker_main";

static bool g_is_connected = 0;

static esp_rmaker_device_t *g_box_state_device;
static esp_rmaker_device_t *g_hr_device;

static int g_box_state = 0;

/* Get the vale of box_state_param */
int get_box_state_param(void)
{
    return g_box_state;
}

void set_box_state_param(int state)
{
    g_box_state = state;
}

esp_err_t app_medication_record_one(void)
{
    return esp_rmaker_param_update_and_report(esp_rmaker_device_get_param_by_name(g_box_state_device, "User_One"), esp_rmaker_float(1.0));
}

esp_err_t app_medication_record_two(void)
{
    return esp_rmaker_param_update_and_report(esp_rmaker_device_get_param_by_name(g_box_state_device, "User_Two"), esp_rmaker_float(1.0));
}

esp_err_t app_hr_data_update(float hr, float sao2)
{
    esp_err_t err = ESP_OK;
    esp_rmaker_param_update_and_report(esp_rmaker_device_get_param_by_name(g_hr_device, "心率"), esp_rmaker_float(hr));
    if (err != ESP_OK) {
        return err;
    }
    err = esp_rmaker_param_update_and_report(esp_rmaker_device_get_param_by_name(g_hr_device, "血氧"), esp_rmaker_float(sao2));
    return err;
}

esp_err_t rmaker_wifi_credential_reset(void)
{
    ESP_LOGW(TAG, "WiFi credential reset");
    return esp_rmaker_wifi_reset(0, 2);
}

/* Callback to handle commands received from the RainMaker cloud */
static esp_err_t write_cb(const esp_rmaker_device_t *device, const esp_rmaker_param_t *param,
            const esp_rmaker_param_val_t val, void *priv_data, esp_rmaker_write_ctx_t *ctx)
{
    if (ctx) {
        ESP_LOGI(TAG, "Received write request via : %s", esp_rmaker_device_cb_src_to_str(ctx->src));
    }

    const char *device_name = esp_rmaker_device_get_name(device);
    const char *param_name  = esp_rmaker_param_get_name(param);

    if (strcmp(device_name, "Medication_Plan") == 0) {
        if (strcmp(param_name, "Open_Box") == 0) {
            ESP_LOGI(TAG, "Received value = %d for %s - %s",
                val.val.i, device_name, param_name);
            g_box_state = val.val.i;
            esp_rmaker_param_update_and_report(param, val);
        } else if (strcmp(param_name, "药盒开关") == 0) {
            ESP_LOGI(TAG, "Received value = %d for %s - %s",
                val.val.b, device_name, param_name);
            if (val.val.b) {
                app_id_check_pass();
                app_open_box();
            }else {
                app_id_check_pass();
                app_close_box();
            }
        } else if (strcmp(param_name, "Notify_User_One") == 0) {
            app_notify_user_one();
            esp_rmaker_raise_alert("彭于晏，该吃药啦！");
        } else if (strcmp(param_name, "Notify_User_Two") == 0) {
            app_notify_user_two();
            esp_rmaker_raise_alert("刘德华，该吃药啦！");
        }

    }
    return ESP_OK;
}

/* This executes in the context of default event loop task */
static void event_handler(void *arg, esp_event_base_t event_base,
                          int32_t event_id, void *event_data)
{
    if (event_base != RMAKER_COMMON_EVENT) {
        return;
    }
    switch (event_id) {
    case RMAKER_MQTT_EVENT_CONNECTED:
        g_is_connected = 1;
        ESP_LOGI(TAG, "RMAKER connected");
        // app_sntp_init();

        bsp_display_lock(0);
        _ui_screen_change(&ui_Screen2, LV_SCR_LOAD_ANIM_FADE_ON, 100, 0, &ui_Screen2_screen_init);
        bsp_display_unlock();
        break;
    case RMAKER_MQTT_EVENT_DISCONNECTED:
        g_is_connected = 0;
        ESP_LOGI(TAG, "RMAKER disconnected");
        bsp_display_lock(0);
        _ui_screen_change(&ui_Screen1, LV_SCR_LOAD_ANIM_FADE_ON, 100, 0, &ui_Screen1_screen_init);
        bsp_display_unlock();
        break;
    default:
        break;
    }
}

static esp_rmaker_device_t *esp_rmaker_medication_device_create()
{
    esp_rmaker_device_t *device = esp_rmaker_device_create("Medication_Plan", NULL, NULL);

    /* Check if device is created */
    if (device) {
        /* Create a parameter to determine which block to open */
        esp_rmaker_param_t *box_state_param = esp_rmaker_param_create("Open_Box", NULL, esp_rmaker_int(0), PROP_FLAG_READ | PROP_FLAG_WRITE);
        /* set the bounds for the medication box */
        esp_rmaker_param_add_bounds(box_state_param, esp_rmaker_int(0), esp_rmaker_int(7), esp_rmaker_int(1));
        esp_rmaker_param_add_ui_type(box_state_param, ESP_RMAKER_UI_DROPDOWN);
        esp_rmaker_device_add_param(device, box_state_param);
        esp_rmaker_device_assign_primary_param(device, box_state_param);

        /* Create a button to turn open/close the box */
        esp_rmaker_param_t *open_box_param = esp_rmaker_param_create("药盒开关", NULL, esp_rmaker_bool(false), PROP_FLAG_WRITE);
        esp_rmaker_param_add_ui_type(open_box_param, ESP_RMAKER_UI_PUSHBUTTON);
        esp_rmaker_device_add_param(device, open_box_param);

        /* Create two parameter to record medication intake data */
        esp_rmaker_param_t *medication_record_one = esp_rmaker_param_create("User_One", NULL, esp_rmaker_float(0.0), PROP_FLAG_READ | PROP_FLAG_TIME_SERIES);
        esp_rmaker_device_add_param(device, medication_record_one);

        esp_rmaker_param_t *medication_record_two = esp_rmaker_param_create("User_Two", NULL, esp_rmaker_float(0.0), PROP_FLAG_READ | PROP_FLAG_TIME_SERIES);
        esp_rmaker_device_add_param(device, medication_record_two);

        /* Create two parameter to notify take medication */
        esp_rmaker_param_t *notify_user_one = esp_rmaker_param_create("Notify_User_One", NULL, esp_rmaker_bool(false), PROP_FLAG_READ | PROP_FLAG_WRITE);
        esp_rmaker_device_add_param(device, notify_user_one);

        esp_rmaker_param_t *notify_user_two = esp_rmaker_param_create("Notify_User_Two", NULL, esp_rmaker_bool(false), PROP_FLAG_READ | PROP_FLAG_WRITE);
        esp_rmaker_device_add_param(device, notify_user_two);

        esp_rmaker_device_add_cb(device, write_cb, NULL);

    }

    return device;
}

static esp_rmaker_device_t *esp_rmaker_hr_device_create()
{
    esp_rmaker_device_t *device = esp_rmaker_device_create("心率检测", NULL, NULL);

    if (device) {
        esp_rmaker_param_t *hr_param = esp_rmaker_param_create("心率", NULL, esp_rmaker_float(0.0), PROP_FLAG_READ | PROP_FLAG_TIME_SERIES);
        esp_rmaker_device_add_param(device, hr_param);
        esp_rmaker_param_t *sao2_param = esp_rmaker_param_create("血氧", NULL, esp_rmaker_float(0.0), PROP_FLAG_READ | PROP_FLAG_TIME_SERIES);
        esp_rmaker_device_add_param(device, sao2_param);
        esp_rmaker_device_assign_primary_param(device, hr_param);
        esp_rmaker_device_add_cb(device, write_cb, NULL);
    }

    return device;

}

static void rmaker_task(void *args)
{
    /* Initialize Wi-Fi. Note that, this should be called before esp_rmaker_node_init()
     */
    app_network_init();

    /* Initialize the ESP RainMaker Agent.
     * Note that this should be called after app_wifi_init() but before app_wifi_start()
     * */
    esp_rmaker_config_t rainmaker_cfg = {
        .enable_time_sync = false,
    };
    esp_rmaker_node_t *node = esp_rmaker_node_init(&rainmaker_cfg, "ESP-Friends", "Medication_Box");
    if (!node) {
        ESP_LOGE(TAG, "Could not initialise node. Aborting!!!");
        vTaskDelay(5000 / portTICK_PERIOD_MS);
        abort();
    }

    /* Create a device to schedule schedule medication times */
    g_box_state_device = esp_rmaker_medication_device_create();
    esp_rmaker_node_add_device(node, g_box_state_device);

    g_hr_device = esp_rmaker_hr_device_create();
    esp_rmaker_node_add_device(node, g_hr_device);

    /* Enable timezone service */
    esp_rmaker_timezone_service_enable();

    /* Enable scheduling */
    esp_rmaker_schedule_enable();

    ESP_ERROR_CHECK(esp_event_handler_register(RMAKER_COMMON_EVENT, ESP_EVENT_ANY_ID, &event_handler, NULL));

    /* Start rmaker Agent */
    esp_rmaker_start();

    /* Start the Wi-Fi */
    esp_err_t err = app_network_start(POP_TYPE_NONE);
    if (err != ESP_OK) {
        ESP_LOGE(TAG, "Could not start Wifi");
    }

    vTaskDelete(NULL);
}

bool app_rmaker_is_connected(void)
{
    return g_is_connected;
}

void app_rmaker_start(void)
{
    BaseType_t ret_val = xTaskCreate(rmaker_task, "RMaker Task", 8 * 1024, NULL, 1, NULL);
    ESP_ERROR_CHECK_WITHOUT_ABORT((pdPASS == ret_val) ? ESP_OK : ESP_FAIL);
}